﻿#define _CRT_SECURE_NO_WARNINGS 1

//操作符 - 进制

//#include<stdio.h>
//
//int main()
//{
//	printf("%d\n", 123);//十进制
//	printf("%d\n", 0123);//八进制
//	printf("%d\n", 0x123);//十六进制
//
//	return 0;
//}


//正整数的原、反、补码都相同    负数的反码:符号位不变,其余位取反 补码:反码 + 1

//#include<stdio.h>
//
//int main()
//{
//	//a是整型类型,占4个字节
//	//00000000000000000000000000000111 - 原码
//	//00000000000000000000000000000111 - 反码
//	//00000000000000000000000000000111 - 补码
//	int a = 7;
//
//	//10000000000000000000000000000111 - 原码
//	//11111111111111111111111111111000 - 反码
//	//11111111111111111111111111111001 - 补码 f9 ff ff ff
//	int b = -7;
//
//
//	return 0;
//}

//#include<stdio.h>
//
//int main()
//{
//	int ret = 7 - 3;//(cpu只有加法器)  => 7 + (-3) 内存中存的是补码 => 补码相加
//
//	//00000000000000000000000000000111 - 7的原码
//	//00000000000000000000000000000111 - 7的反码
//	//00000000000000000000000000000111 - 7的补码
//
//	//10000000000000000000000000000011 - -3的原码
//	//11111111111111111111111111111100 - -3的反码
//	//11111111111111111111111111111101 - -3的补码
//
//	// 7 + (-3)
//	//00000000000000000000000000000111 - 7的补码
//	//11111111111111111111111111111101 - -3的补码
//	//00000000000000000000000000000100 - ret的补码
//	//00000000000000000000000000000100 - ret的反码
//	//00000000000000000000000000000100 - ret的原码
//
//	printf("ret = %d\n", ret);
//
//	return 0;
//}


//移位操作符 -- 注：移位操作符的操作数只能是整数。

////<< 左移操作符 -- 移位规则：左边抛弃、右边补0
//#include<stdio.h>
//
//int main()
//{
//	////正数左移
//	//int a = 7;
//	//int b = a << 1;
//
//	////00000000000000000000000000000111 - 7的原码
//	////00000000000000000000000000000111 - 7的反码
//	////00000000000000000000000000000111 - 7的补码
//
//	////00000000000000000000000000001110 - 7的补码左移1位的补码 => 
//	////00000000000000000000000000001110 - 反码
//	////00000000000000000000000000001110 - 原码
//
//	//printf("a = %d\n", a);//7
//	//printf("b = %d\n", b);//14
//
//	////负数
//	int a = -7;
//	int b = a << 1;
//
//	//10000000000000000000000000000111 - -7的原码
//	//11111111111111111111111111111000 - -7的反码
//	//11111111111111111111111111111001 - -7的补码
//
//	//11111111111111111111111111110010 - -7的补码左移1位的补码 => 
//	//10000000000000000000000000001101 - 反码
//	//10000000000000000000000000001110 - 原码
//
//	printf("a = %d\n", a);//-7
//	printf("b = %d\n", b);//-14
//
//	return 0;
//}

////>> 右移操作符 -- 移位规则：1. 逻辑右移：左边⽤0填充，右边丢弃 2. 算术右移：左边⽤原该值的符号位填充，右边丢弃
////常见的编译器采用算术右移
//#include<stdio.h>
//
//int main()
//{
//	////正数右移
//	//int a = 7;
//	//int b = a >> 1;
//
//	////00000000000000000000000000000111 - 7的原码
//	////00000000000000000000000000000111 - 7的反码
//	////00000000000000000000000000000111 - 7的补码
//
//	////00000000000000000000000000000011 - 7的补码右移1位的补码
//	////00000000000000000000000000000011 - 反码
//	////00000000000000000000000000000011 - 原码
//
//	//printf("a = %d\n", a);//7
//	//printf("b = %d\n", b);//3
//
//
//	//负数数右移
//	int a = -7;
//	int b = a >> 1;
//
//	//10000000000000000000000000000111 - -7的原码
//	//11111111111111111111111111111000 - -7的反码
//	//11111111111111111111111111111001 - -7的补码
//
//	//11111111111111111111111111111100 - -7的补码右移1位的补码 fc ff ff ff
//	//10000000000000000000000000000011 - 反码
//	//10000000000000000000000000000100 - 原码
//
//	printf("a = %d\n", a);//-7
//	printf("b = %d\n", b);//-4
//
//	return 0;
//}

//警告⚠️：对于移位运算符，不要移动负数位，这个是标准未定义的。

//位操作符：
// & --> 按位与
// | --> 按位或
// ^ --> 按位异或
// ~ --> 按位取反
//注：他们的操作数必须是整数。

//#include<stdio.h>
//s
//////& --> 按位与
////int main()
////{
////	int a = 3;
////	int b = -7;
////	int ret = a & b;
////	//使用补码按位&,有0则为0,同1为1
////	//00000000000000000000000000000011 - 3的原码
////	//00000000000000000000000000000011 - 3的反码
////	//00000000000000000000000000000011 - 3的补码
////	
////	//10000000000000000000000000000111 - -7的原码
////	//11111111111111111111111111111000 - -7的反码
////	//11111111111111111111111111111001 - -7的补码
////	//00000000000000000000000000000011 - 3的补码
//// 
////	//00000000000000000000000000000001 - ret的补码 01 00 00 00
////	//00000000000000000000000000000001 - ret的反码
////	//00000000000000000000000000000001 - ret的原码
////
////	printf("ret = %d\n", ret);//1
////
////	return 0;
////}
//
////// | --> 按位或
////int main()
////{
////	int a = 3;
////	int b = -7;
////	int ret = a | b;
////	//使用补码按位|,有1则为1,全0为0
////	//00000000000000000000000000000011 - 3的原码
////	//00000000000000000000000000000011 - 3的反码
////	//00000000000000000000000000000011 - 3的补码
////
////	//10000000000000000000000000000111 - -7的原码
////	//11111111111111111111111111111000 - -7的反码
////	//11111111111111111111111111111001 - -7的补码
////	//00000000000000000000000000000011 - 3的补码
////
////	//11111111111111111111111111111011 - ret的补码 fb ff ff ff
////	//10000000000000000000000000000100 - ret的反码
////	//10000000000000000000000000000101 - ret的原码
////
////	printf("ret = %d\n", ret);//-5
////
////	return 0;
////}
//
////// ^ --> 按位异或
////int main()
////{
////	int a = 3;
////	int b = -7;
////	int ret = a ^ b;
////	//使用补码按位异或,不同为1,相同为0
////	//00000000000000000000000000000011 - 3的原码
////	//00000000000000000000000000000011 - 3的反码
////	//00000000000000000000000000000011 - 3的补码
////
////	//10000000000000000000000000000111 - -7的原码
////	//11111111111111111111111111111000 - -7的反码
////	//11111111111111111111111111111001 - -7的补码
////	//00000000000000000000000000000011 - 3的补码
////
////	//11111111111111111111111111111010 - ret的补码 fa ff ff ff
////	//10000000000000000000000000000101 - ret的反码
////	//10000000000000000000000000000110 - ret的反码
////
////	printf("ret = %d\n", ret);//-6
////
////	return 0;
////}
//
//// ~ --> 按位取反
//int main()
//{
//	int a = 3;
//	int b = -7;
//	int ret1 = ~a;
//	int ret2 = ~b;
//	//使用补码按位取反,1变为0,0变为1
//	//00000000000000000000000000000011 - 3的原码
//	//00000000000000000000000000000011 - 3的反码
//	//00000000000000000000000000000011 - 3的补码
//
//	//11111111111111111111111111111100 - ret1的补码 fc ff ff ff
//	//10000000000000000000000000000011 - ret1的反码
//	//10000000000000000000000000000100 - ret1的原码
//
//	//10000000000000000000000000000111 - -7的原码
//	//11111111111111111111111111111000 - -7的反码
//	//11111111111111111111111111111001 - -7的补码
//
//	//00000000000000000000000000000110 - ret2的补码 06 00 00 00
//	//00000000000000000000000000000110 - ret2的反码
//	//00000000000000000000000000000110 - ret2的原码
//
//	printf("ret1 = %d\n", ret1);//-4
//	printf("ret2 = %d\n", ret2);//6
//
//	return 0;
//}

////写一个代码,实现两个整数的交换。
//#include<stdio.h>
//
//int main()
//{
//	int a = 3;
//	int b = 7;
//	int tmp = 0;
//	printf("交换前:a = %d,b = %d\n", a, b);
//
//	tmp = a;
//	a = b;
//	b = tmp;
//	printf("交换前:a = %d,b = %d\n", a, b);
//
//	return 0;
//}

////写一个代码,不能创建临时变量(第三个变量),实现两个整数的交换。
//#include<stdio.h>
//
//////方法一  缺点:如果a+b过大会导致int存不下溢出
////int main()
////{
////	int a = 3;
////	int b = 7;
////	printf("交换前:a = %d,b = %d\n", a, b);
////
////	a = a + b;//10
////	b = a - b;//3
////	a = a - b;//7
////
////	printf("交换后:a = %d,b = %d\n", a, b);
////
////	return 0;
////}
//
////异或的补充:
////a ^ a = 0 , a ^ 0 = a
////(假设a = 7) 
////111 ^ 111 = 000 = 0, 111 ^ 000 = 111
////a ^ a ^ b = a ^ b ^ a
//// (假设b = 3) 111 ^ 111 ^ 011 = 000 ^ 011 = 011 <=> 111 ^ 011 ^ 111 = 100 ^ 111 = 011
//
////方法二
//int main()
//{
//	int a = 3;
//	int b = 7;
//	printf("交换前:a = %d,b = %d\n", a, b);
//
//	a = a ^ b;
//	b = a ^ b;//a ^ b ^ b = a ^ 0 = a
//	a = a ^ b;//a ^ a ^ b = 0 ^ b = b
//	printf("交换后:a = %d,b = %d\n", a, b);
//
//	return 0;
//}

////编写代码实现：求⼀个整数存储在内存中的⼆进制中1的个数。
//#include<stdio.h>
//
//////方法一 //参数需要加上unsigned,不然负数就会出问题
////int count_one_of_binary(unsigned int n)
////{
////	int cnt = 0;
////	while (n)
////	{
////		if (1 == n % 2)
////			cnt++;
////		n /= 2;
////	}
////	return cnt;
////}
//
//////方法二  效率上面可能没那么高
////int count_one_of_binary(int n)
////{
////	int cnt = 0;
////	int i = 0;
////	for (int i = 0; i < 32; i++)
////	{
////		if (1 == ((n >> i) & 1))
////			cnt++;
////	}
////
////	return cnt;
////}
//
////方法三  
//int count_one_of_binary(int n)
//{
//	int cnt = 0;
//	int i = 0;
//	while (n)
//	{
//		cnt++;
//		n &= (n - 1);// n = n & (n - 1)
//	}
//
//	return cnt;
//}
//
//int main()
//{
//	int num = 0;
//	scanf("%d", &num);
//
//	int ret = count_one_of_binary(num);
//
//	printf("二进制中1的个数:ret = %d\n", ret);
//
//	return 0;
//}


//编写代码将13⼆进制序列的第5位修改为1，然后再改回0
#include<stdio.h>

int main()
{
	int num = 13;

	//⼆进制序列的第5位修改为1
	//00000000000000000000000000001101 - 13原码
	//00000000000000000000000000001101 - 13反码
	//00000000000000000000000000001101 - 13补码
	//00000000000000000000000000010000 - 1 << (5 - 1) 然后再 |
	num = num | (1 << (5 - 1));
	//00000000000000000000000000011101 - 补码
	//00000000000000000000000000011101 - 反码
	//00000000000000000000000000011101 - 原码
	printf("二进制序列的第5位修改为1: %d\n", num);

	//再改回0
	//00000000000000000000000000011101 - 补码
	//11111111111111111111111111101111 - ~(1 << (5 - 1)) 然后再 &
	num = num & ~(1 << (5 - 1));
	//00000000000000000000000000001101 - 补码
	//00000000000000000000000000001101 - 反码
	//00000000000000000000000000001101 - 原码
	printf("再改回0: %d\n", num);

	return 0;
}











